package com.zk.bytecode.trace;

import java.util.Arrays;
import java.util.List;

/**
 * 记录 StackTrace执行过程树和trace状态
 */
public class StackTraceManagement {
    private static final ThreadLocal<StackTraceManagement> stackTraceHolder = new ThreadLocal<>();
    private int count = 0;
    private boolean traced = false;
    private ElementTree root;

    public static StackTraceManagement get() {
        StackTraceManagement holder = stackTraceHolder.get();
        if (holder == null) {
            holder = StackTraceManagement.create();
            stackTraceHolder.set(holder);
        }
        return holder;
    }

    public boolean isTraced() {
        return traced;
    }

    static StackTraceManagement create() {
        StackTraceManagement holder = new StackTraceManagement();
        holder.initElements();
        return holder;
    }

    /**
     * 记录跟踪StackTrace
     */
    public void trace() {
        List<StackTraceElement> stackTrace = stackTrace(4); // 本方法工具层级为4
        root.mergeStack(stackTrace);
        traced = true;
    }

    private void initElements() {
        List<StackTraceElement> stackTraceElements = stackTrace(6); // 调用层级深度为6
        this.root = ElementTree.createRoot(stackTraceElements);
    }


    /**
     * 从StackTraceElement数组中，移出本装置相关的Elements
     */
    private List<StackTraceElement> stackTrace(final int stackDepth) {
        StackTraceElement[] stackTraces = Thread.currentThread().getStackTrace();
        List<StackTraceElement> list = Arrays.asList(stackTraces);
        return list.subList(stackDepth, list.size());
    }

    int increase() {
        traced = false;
        ++count;
        return count;
    }

    int decrease() {
        --count;
        if (count == 0) {
            stackTraceHolder.remove();
        }
        return count;
    }
}
